﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.Data.Common;
using System.Net;
using System.IO;
namespace DotNet.Common.Kit
{
    public class ShiftIPHelper
    {
        #region 类的私的函数，用来处理内部信息
        private static string GetWanPara(string htmlStr,string key)
        {
            string ret = "";
            HtmlDocHelper htmlDoc = new HtmlDocHelper(htmlStr);
            string script = htmlDoc.GetNodeKeyWord("//script",key);
            //HtmlAgilityPack.HtmlNodeCollection hnc = null;// GlobalFun.ParaseToHtml(htmlStr).DocumentNode.SelectNodes("//script");
            if (script != "")
            {
                string[] ipArr =script.Split(',');
                if (ipArr.Length > 2)
                    ret = ipArr[2].Trim(new char[] { '"', '\n' });
            }
            return ret;
        }
        private static int UpdateIpUseNum(string ip,int useNum)
        {
            if (ip == "") ip = "本机IP";
            string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\ShiftIP.mdb;Persist Security Info=False";
            DbHelper db = new DbHelper(strConn, "System.Data.OleDb");
            string strSql = "update proxyIp set usenum=" + useNum + " where ip='" + ip + "'";
            try
            {
                DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                db.ExecuteNonQuery(cmd);
            }
            catch (Exception ex)
            {
                LocLoggerHelper.WriteException("ShiftIPHelper", ex);
                return 0;
            }
            return 1;
        }
        private static int InsertNewIp(string ip)
        {
            System.Data.DataSet ds = GetIP(ip);
            if (ds != null)
            {
                DataRowCollection dr = ds.Tables[0].Rows;
                if (dr.Count != 0)  //存在该 IP 则将useNum+1
                {
                    UpdateIp(ip, "useNum:" + dr[0]["useNum"].ToString());
                    return 1;
                }
                else
                {
                    try
                    {
                        string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\ShiftIP.mdb;Persist Security Info=False";
                        DbHelper db = new DbHelper(strConn, "System.Data.OleDb");                                     //路由才会加入IP，因此userflag=0
                        string strSql = "INSERT INTO proxyIp ( ip, usenum, useflag, succ, fail ) VALUES ('" + ip + "'" + ",1, 0, 0, 0)";
                        DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                        return db.ExecuteNonQuery(cmd);
                    }
                    catch (Exception ex)
                    {
                        LocLoggerHelper.WriteException("ShiftIPHelper", ex);
                        return 0;
                    }
                }
            }
            return 0;

        }
        private static System.Data.DataSet GetIP(string ip)
        {
            try
            {
                string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\ShiftIP.mdb;Persist Security Info=False";
                DbHelper db = new DbHelper(strConn, "System.Data.OleDb");
                string strSql = "select *from proxyIp where ip='"+ip+"'";
                DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                return db.ExecuteDataSet(cmd);
            }
            catch (Exception ex)
            {
                LocLoggerHelper.WriteException("ShiftIPHelper", ex);
                return null;
            }
        }
        private static bool IsExist(string ip)
        {
            try
            {
                string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\ShiftIP.mdb;Persist Security Info=False";
                DbHelper db = new DbHelper(strConn, "System.Data.OleDb");
                string strSql = "select *from proxyIp where ip='"+ip;
                DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                object obj = db.ExecuteScalar(cmd);
                if (obj == null)
                    return false;
                else
                    return true;
            }
            catch (Exception ex)
            {
                LocLoggerHelper.WriteException("ShiftIPHelper", ex);
                return false;
            }
        }
        /// <summary>
        /// 更新IP信息，可变量
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="col">colName:value的形式</param>
        /// <returns></returns>
        private static int UpdateIp(string ip,params string[] col)
        {
            try
            {
                System.Data.DataSet ds = GetIP(ip);
                string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\ShiftIP.mdb;Persist Security Info=False";
                DbHelper db = new DbHelper(strConn, "System.Data.OleDb");
                string strSql = "update proxyIp set ";// useflag=1 where ip='" + ip + "'";
                foreach (string colName in col)
                {
                    string[] temp=colName.Split(':');
                    string cName = temp[0];
                    string val = "";
                    if(cName=="succ"||cName=="fail")
                    {
                        val = (Convert.ToInt32(temp[1]) + Convert.ToInt32(ds.Tables[0].Rows[0][cName].ToString())).ToString();
                    }
                    else 
                        val = temp[1];
                    strSql += cName+"="+val+",";

                }
                strSql=strSql.TrimEnd(',');
                if (ip != "")
                {
                    strSql=strSql+" where ip='" + ip + "'";
                    DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                    return db.ExecuteNonQuery(cmd);
                }
                
            }
            catch (Exception ex)
            {
                LocLoggerHelper.WriteException("ShiftIPHelper", ex);
                return 0;
            }
            return 1;
        }
        private static string GetFastIP(ref int ipCount,ref int useNum)
        {
            string retIp = "";
            try
            {
                string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\ShiftIP.mdb;Persist Security Info=False";
                DbHelper db = new DbHelper(strConn, "System.Data.OleDb");
                string strSql = "select *from proxyIp where useflag=1 order by vtime asc"; //保证使用最快的IP
                DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                System.Data.DataTable dt = db.ExecuteDataTable(cmd);
                ipCount = dt.Rows.Count;
                if (ipCount > 0)
                {
                    retIp = dt.Rows[0]["ip"].ToString();
                    useNum = Convert.ToInt32(dt.Rows[0]["useNum"]);
                    if (retIp == "本机IP")
                        return "";
                    else
                        return retIp;
                }
                else
                    return retIp;
            }
            catch(Exception ex)
            {
                LocLoggerHelper.WriteException("ShiftIPHelper", ex);
                return "";
            }
        }
        /// <summary>
        /// 更新IP访问的时间。
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="time"></param>
        public static void RefreshTime(string ip, long time)
        {
            string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + System.Windows.Forms.Application.StartupPath + "\\taobaoInfo.mdb;Persist Security Info=False";
            try
            {
                DbHelper db = new DbHelper(strConn, "System.Data.OleDb");
                string strSql = "select *from proxyIp where ip='" + ip + "'";
                DbCommand cmd = db.GetSqlStringCommond(strSql) as OleDbCommand;
                object obj = db.ExecuteScalar(cmd);
                if (obj != null)
                {
                    string updateSql = "update proxyIp set vtime=" + time + " where ip='" + ip + "'";
                    cmd = db.GetSqlStringCommond(updateSql) as OleDbCommand;
                    db.ExecuteNonQuery(cmd);
                }
                else
                {
                    if (ip.Contains("本机IP"))
                    {
                        string updateSql = "update proxyIp set vtime=" + time + " where ip='本机IP'";
                        cmd = db.GetSqlStringCommond(updateSql) as OleDbCommand;
                        db.ExecuteNonQuery(cmd);
                    }
                }
            }
            catch (Exception ex)
            {
                LocLoggerHelper.WriteException(ex);
            }
        }
        #endregion

        #region  两个主要的类，用来重启路由和得到代理IP
        private static string RestartRouter()
        {
            IniHelper ini = new IniHelper("ShiftIP.ini");
            string routerUserName = ini.GetKeyValue("Router", "username");//用户访问Router的用户名和密码
            string routerPwd = ini.GetKeyValue("Router", "pwd");
            string disUrl = ini.GetKeyValue("Router", "disUrl");
            string reNewUrl = ini.GetKeyValue("Router", "reNewUrl");
            string routerIp = ini.GetKeyValue("Router", "IP");
            string wanIPKey = ini.GetKeyValue("Router", "wanIP"); //重启路由后返回IP的特征串。
            if (routerUserName == "" || routerPwd == "" || disUrl == "" || reNewUrl == "" || routerIp == "" || wanIPKey=="")
            {
                LocLoggerHelper.WriteErrorLog("ShiftIP", "读取INI文件值为空");
                return "";
            }
            string sDomain = "";
            //更新，断线 访问的URL，
            //string disUrl = "http://192.168.1.1/userRpm/StatusRpm.htm?Disconnect=" + System.Web.HttpUtility.UrlEncode("断 线", System.Text.Encoding.GetEncoding("gb2312")) + "&wan=1";
            //string reNewUrl = "http://192.168.1.1/userRpm/StatusRpm.htm?RenewIp=" + System.Web.HttpUtility.UrlEncode("更 新", System.Text.Encoding.GetEncoding("gb2312")) + "&wan=1";
            string renewIp = "";
            try
            {
                HttpHelper http = new HttpHelper();
                HttpItem item = new HttpItem();
                item.Referer = routerIp;
                item.Method = "GET";
                item.ContentType = "application/x-www-form-urlencoded";
                item.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6.4; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
                item.Allowautoredirect = true;
                item.Credentials = new NetworkCredential(routerUserName, routerPwd, sDomain);

                item.URL = disUrl;
                string htmlStr = http.GetHtml(item).Html;
                renewIp = GetWanPara(htmlStr, wanIPKey);
                while (renewIp.Contains("0.0.0.0"))
                {
                    System.Threading.Thread.Sleep(1000);
                    item.URL = reNewUrl;
                    htmlStr = http.GetHtml(item).Html;
                    renewIp = GetWanPara(htmlStr, wanIPKey);
                }
                InsertNewIp(renewIp);
            }
            catch (Exception ex)
            {
                LocLoggerHelper.WriteException("shiftip",ex);
            }
            return renewIp;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ipCount">可用ip个数</param>
        /// <returns></returns>
        private static string ProxyIp(ref int ipCount)
        {
            IniHelper ini = new IniHelper("ShiftIP.ini");
            string testUrl = ini.GetKeyValue("ProxyTestURL", "url"); //测试代理IP是否可用的url
            string testUrlKey = ini.GetKeyValue("ProxyTestURL", "keyword"); //url中的特征值。
            if (testUrl == "" || testUrlKey == "")
            {
                LocLoggerHelper.WriteErrorLog("ShiftIPHelper", "INI文件测试代理IP的ProxyTestURL配置不正确");
                return "";
            }
            else
            {
                int useNum = 0;

                HttpHelper http = new HttpHelper();
                HttpItem item = new HttpItem();
                item.URL = testUrl;
                item.Timeout = 9000;
                item.UserAgent = "Mozilla/4.0+(compatible;+MSIE+8.0;+Windows+NT+5.1;+Trident/4.0;+.NET4.0C;+.NET4.0E;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.4506.2152;+.NET+CLR+3.5.30729)";
                item.ProxyIp = GetFastIP(ref ipCount, ref useNum);
                string htmlStr = http.GetHtml(item).Html;
                while (!htmlStr.Contains(testUrlKey)) //没有得到验证串(自己服务器上面配置的串)
                {
                    UpdateIp(item.ProxyIp,"useflag:0");  //将IP使用标识改0 不可用
                    item.ProxyIp = GetFastIP(ref ipCount, ref useNum);
                    htmlStr = http.GetHtml(item).Html;
                }
                UpdateIpUseNum(item.ProxyIp, useNum);
                return item.ProxyIp;
            }
        }
        #endregion 

        #region 公用函数，供外部调用
        /// <summary>
        /// 含有换IP的条件
        /// </summary>
        /// <param name="dict"></param>
        /// <param name="htmlStrTitle"></param>
        /// <returns></returns>
        public static bool ExistShiftIp(Dictionary<string, string> dict, string htmlStrTitle)
        {
            string[] temp=htmlStrTitle.Split(',', '-', ':', '。');
            string str = temp[temp.Length-1].Trim();
            if (str == "") return false;
            else
            {
                foreach (KeyValuePair<string, string> item in dict)
                {
                    if (item.Value.ToString().Contains(str))
                        return true;
                }
            }
            return false;
        }

        public static int UpdateIpInfo(string ip,ref double vtime, ref int succCount, ref int failCount)
        {
            string vtime1="vtime:"+vtime;
            string succ="succ:"+succCount;
            string fail="fail:"+failCount;
            UpdateIp(ip, vtime1, succ, fail);
            return 1;
        } 
/// <summary>
///得到切换IP  , ref string vtime,ref int succCount,ref int failCount
/// </summary>
        /// <param name="ipCount">可用IP的总个数，路由器访问则为-1</param>
/// <param name="proxyFlag">1:代理IP访问，0：路由IP</param>
/// <returns></returns>
        public static string GetShiftIp(ref int ipCount,ref int proxyFlag)
        {
            IniHelper ini = new IniHelper("ShiftIP.ini");
            string proxy = ini.GetKeyValue("ProxyUseFlag", "proxy");  //得到切换IP或重启路由条件
            string retIp = "";
            if (proxy == "1")  //得到代理IP
            {
                proxyFlag=1;
                retIp = ProxyIp(ref ipCount);
            }
            else if (proxy == "0")  //重启路由IP
            {
                ipCount = -1;
                proxyFlag=0;
                retIp=RestartRouter();
            }
            else
            {
                LocLoggerHelper.WriteErrorLog("ShiftIP", "INI中ProxyUseFlag节的proxy段信息错误");
            }
            return retIp;
        }
        #endregion
    }
}
